﻿using System;
using System.Runtime.InteropServices;

namespace Btstack
{
    public class Btstack
    {
        /**
        * Address types
        * @note: BTstack uses a custom addr type to refer to classic ACL and SCO devices
        */
        public enum BdAddrType
        {
            LePublic = 0,
            LeRandom = 1,
            LePrivatFallbackPublic = 2,
            LePrivatFallbackRandom = 3,
            Sco = 0xfc,
            Acl = 0xfd,
            Unknown = 0xfe  // also used as 'invalid'
        }

        public delegate void PacketHandlerType(byte type, ushort channel, IntPtr packet, ushort size);

        public const byte BTSTACK_EVENT_STATE = 0x60;
        public const byte BTSTACK_EVENT_NR_CONNECTIONS_CHANGED = 0x61;
        public const byte BTSTACK_EVENT_POWERON_FAILED = 0x62;
        public const byte BTSTACK_EVENT_DISCOVERABLE_ENABLED = 0x66;

        public const byte BLUETOOTH_DATA_TYPE_FLAGS = 0x01; // Flags
        public const byte BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x02; // Incomplete List of 16-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x03; // Complete List of 16-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x04; // Incomplete List of 32-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x05; // Complete List of 32-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x06; // Incomplete List of 128-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x07; // Complete List of 128-bit Service Class UUIDs
        public const byte BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME = 0x08; // Shortened Local Name
        public const byte BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME = 0x09; // Complete Local Name
        public const byte BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL = 0x0A; // Tx Power Level
        public const byte BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE = 0x0D; // Class of Device
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C = 0x0E; // Simple Pairing Hash C
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_192 = 0x0E; // Simple Pairing Hash C-192
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F; // Simple Pairing Randomizer R
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_192 = 0x0F; // Simple Pairing Randomizer R-192
        public const byte BLUETOOTH_DATA_TYPE_DEVICE_ID = 0x10; // Device ID
        public const byte BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_TK_VALUE = 0x10; // Security Manager TK Value
        public const byte BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11; // Security Manager Out of Band Flags
        public const byte BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12; // Slave Connection Interval Range
        public const byte BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14; // List of 16-bit Service Solicitation UUIDs
        public const byte BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15; // List of 128-bit Service Solicitation UUIDs
        public const byte BLUETOOTH_DATA_TYPE_SERVICE_DATA = 0x16; // Service Data
        public const byte BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID = 0x16; // Service Data - 16-bit UUID
        public const byte BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS = 0x17; // Public Target Address
        public const byte BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS = 0x18; // Random Target Address
        public const byte BLUETOOTH_DATA_TYPE_APPEARANCE = 0x19; // Appearance
        public const byte BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL = 0x1A; // Advertising Interval
        public const byte BLUETOOTH_DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B; // LE Bluetooth Device Address
        public const byte BLUETOOTH_DATA_TYPE_LE_ROLE = 0x1C; // LE Role
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_256 = 0x1D; // Simple Pairing Hash C-256
        public const byte BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E; // Simple Pairing Randomizer R-256
        public const byte BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F; // List of 32-bit Service Solicitation UUIDs
        public const byte BLUETOOTH_DATA_TYPE_SERVICE_DATA_32_BIT_UUID = 0x20; // Service Data - 32-bit UUID
        public const byte BLUETOOTH_DATA_TYPE_SERVICE_DATA_128_BIT_UUID = 0x21; // Service Data - 128-bit UUID
        public const byte BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22; // LE Secure Connections Confirmation Value
        public const byte BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23; // LE Secure Connections Random Value
        public const byte BLUETOOTH_DATA_TYPE_URI = 0x24; // URI
        public const byte BLUETOOTH_DATA_TYPE_INDOOR_POSITIONING = 0x25; // Indoor Positioning
        public const byte BLUETOOTH_DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26; // Transport Discovery Data
        public const byte BLUETOOTH_DATA_TYPE_LE_SUPPORTED_FEATURES = 0x27; // LE Supported Features
        public const byte BLUETOOTH_DATA_TYPE_CHANNEL_MAP_UPDATE_INDICATION = 0x28; // Channel Map Update Indication
        public const byte BLUETOOTH_DATA_TYPE_PB_ADV = 0x29; // PB-ADV
        public const byte BLUETOOTH_DATA_TYPE_MESH_MESSAGE = 0x2A; // Mesh Message
        public const byte BLUETOOTH_DATA_TYPE_MESH_BEACON = 0x2B; // Mesh Beacon
        public const byte BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA = 0x3D; // 3D Information Data
        public const byte BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; // Manufacturer Specific Data

        [DllImport("btstack-c.dll", EntryPoint = "btstack_memory_init")]
        public static extern void MemoryInit();

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_init")]
        public static extern void RunLoopInit(IntPtr run_loop);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_windows_get_instance")]
        public static extern IntPtr RunLoopWindowsGetInstance();

        [DllImport("btstack-c.dll", EntryPoint = "btstack_chipset_intel_download_firmware")]
        public static extern void ChipsetIntelDownloadFirmware(IntPtr transport, Action<int> callback);

        [DllImport("btstack-c.dll", EntryPoint = "btstack_run_loop_execute")]
        public static extern void RunLoopExecute();

        [DllImport("btstack-c.dll", EntryPoint = "uuid128_to_str")]
        private static extern string Uuid128ToStr(IntPtr uuid);

        public static byte EventStateGetState(byte[] packet)
        {
            return packet[2];
        }

        public static string Uuid128ToStr(byte[] uuid)
        {
            IntPtr UuidPtr = Marshal.AllocHGlobal(16);
            Marshal.Copy(uuid, 0, UuidPtr, 16);

            var str = Uuid128ToStr(UuidPtr);

            Marshal.FreeHGlobal(UuidPtr);

            return str;
        }
    }
}
